#include <stdio.h>
#include "tcp_data_handler.h"
#include "tcp_acceptor.h"
#include "application.h"
#include "system_util.h"

using namespace kingnet ;

class test_app ;
DECLARE_APPLICATION_INSTANCE(test_app) ;

class test_connection : public tcp_data_handler
{
public:
    test_connection()
    {
        m_last_time = time(0) ;
        m_counter = 0 ;
        m_timer.set_owner(this) ;
    }
    virtual ~test_connection() { fini() ; } ;

    int get_packet_info(const char* data,int size,packet_info* pi)
    {
        pi->data = data ;
        pi->size =size ;
        return 0 ;
    }
    
    int process_packet(const packet_info* pi)
    {
        m_last_time = time(0) ;
        start_ping() ;
        return 0 ;
    }
    
    void on_connected() ;
    void on_closed(int type,int no) ;


    void on_timeout(timer_manager* manager) ;

    void start_ping() ;
private:
    int m_last_time ;
    int m_counter ; 
    template_timer<test_connection,&test_connection::on_timeout> m_timer ; 


} ; 

class test_acceptor : public tcp_acceptor
{
public:
    int on_connection(int fd,sa_in_t* addr) ;

private:


};

class test_app : public application
{
public:
    test_app()
    {
        m_client_count = 1 ;
        m_client_finished = 0 ;
    }

    int on_init()
    {
        //m_acceptor.init(&event_engine,"0.0.0.0",9999) ;
        conn_table = new test_connection[m_client_count] ;
        if(conn_table == 0 ) return -1 ;
        set_timer(10000) ;
        
        printf("start time:%ld\n",time_ms()) ;
        m_start_time = time_ms() ;
        for(int i = 0 ; i < m_client_count; ++i)
        {
            test_connection* conn = conn_table + i ;
            if(conn->init(&reactor(),"127.0.0.1",9999)!=0)
            {
                error_return(-1,"connect failed") ;
            }
            set_socket_nodelay(conn->get_id().fd) ;

        }
        return 0 ;
    }

    void on_fini()
    {
        m_acceptor.fini() ;
        delete[] conn_table ;
    }

    void on_client_finished(test_connection* conn)
    {
        ++m_client_finished ;
        if(m_client_finished == m_client_count )
        {
            printf("consume time:%lld\n",time_ms() - m_start_time ) ;
            printf("finish time:%lld\n",time_ms()) ;
            set_status(STATUS_STOP) ;
        }
    }

    void on_timer()
    {
        printf("app timeout\n") ;
    }

public:
    test_connection* conn_table ;
private:
    test_acceptor m_acceptor ;
    int m_client_finished ; 
    int m_client_count ;
    int64_t m_start_time ;

} ;

void test_connection::on_connected()
{
    printf("client::on_connected\n") ;
    m_last_time = time(0) ;
    get_app().add_timer(&m_timer,200000) ;
    start_ping() ;
}


void test_connection::start_ping()
{
    if( m_counter < 10)
    {
        if( this->send("ping",4,0) == 0 ) ++m_counter ;
    }
    else
    {
        get_app().on_client_finished(this) ;
    }
}

void test_connection::on_closed(int type,int no)
{
    printf("disconnect type:%d\n",type) ;
    get_app().del_timer(&m_timer) ;
}

void test_connection::on_timeout(timer_manager* manager)
{
        int now = time(0) ;
        if(now - m_last_time > 10)
        {
            printf("connection timeout\n");
            fini() ;
            return ;
        }


}




int test_acceptor::on_connection(int fd,sa_in_t* addr)
{
    test_connection& conn = get_app().conn_table[fd] ;
    if( conn.init(m_reactor,fd)!=0) return -1 ;

    printf("accept fd %d\n",fd) ;
    return 0 ;
}


IMPLEMENT_APPLICATION_INSTANCE(test_app) ;
IMPLEMENT_MAIN() ;
